import streamlit as st
from PIL import Image
import numpy as np
from io import BytesIO
import shutil
import sys


ASCII_CHARS = "@%#*+=-:. "


def image_to_ascii(img: Image.Image, new_width: int | None = None) -> str:
    """Convert PIL Image to ASCII art string sized to terminal width by default."""
    # convert to grayscale
    gray = img.convert("L")

    # determine target width: use terminal width if not provided
    term_cols = shutil.get_terminal_size((80, 24)).columns
    if new_width is None:
        new_width = min(term_cols, 120)

    orig_width, orig_height = gray.size
    if orig_width == 0:
        return ""

    # characters are taller than wide in terminal; use scale factor
    char_aspect = 0.55
    new_height = max(1, int((orig_height / orig_width) * new_width * char_aspect))

    resized = gray.resize((new_width, new_height))
    arr = np.array(resized)

    n_chars = len(ASCII_CHARS)
    lines = []
    for row in arr:
        line = "".join(ASCII_CHARS[int((255 - px) / 255 * (n_chars - 1))] for px in row)
        lines.append(line)

    return "\n".join(lines)


def main():
    st.title("图片转 ASCII — 终端输出")
    st.write(
        "把图片拖到下面的区域，ASCII 字符画会打印到运行此 Streamlit 的终端（控制台）。"
    )

    uploaded = st.file_uploader(
        "拖放图片到这里（png/jpg/jpeg/bmp/gif）",
        type=["png", "jpg", "jpeg", "bmp", "gif"],
    )

    if uploaded is not None:
        try:
            img = Image.open(BytesIO(uploaded.read()))
        except Exception as e:
            st.error(f"无法读取图片：{e}")
            return

        st.image(img, caption="已上传图片", use_column_width=True)

        st.info("正在将图片转换为 ASCII，并在终端输出，请查看启动该服务的终端窗口。")

        ascii_art = image_to_ascii(img)

        # Print to the terminal where streamlit was started
        print(ascii_art)
        sys.stdout.flush()

        st.success("ASCII 艺术已打印到启动该应用的终端。")


if __name__ == "__main__":
    main()
